﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TransportLayer.NodeLibrary
{
    /**
     * Urządzenie odbierające ze swojego portu ruch sieciowy. 
     **/
    public class Sink : Cleaner
    {
        private int id;
        public int Id { get { return id; } }

        private string name;
        public string Name { get { return name; } set { name = value; } }

        private Log log;
        public Log Log { get { return log; } }

        private SinkSNP snp;
        public SinkSNP Snp { get { return snp; } }

        private PortIn portIn;
        public PortIn PortIn { get { return portIn; } }

        public class SinkReceiver : IFrameReceiver
        {
            private Sink sink;
            private Dictionary<RoutingEntry, string> sources = new Dictionary<RoutingEntry, string>(new RoutingEntry.REComparer());
            public Dictionary<RoutingEntry, string> Sources { get { return sources; } set { sources = value; } }
            private Dictionary<int, RoutingEntry> connections = new Dictionary<int, RoutingEntry>();
            public Dictionary<int, RoutingEntry> Connections{ get { return connections; } set { connections = value; }}
            public String Buffer;

            public SinkReceiver(Sink sink)
            {
                this.sink = sink;
            }

            public void ReceiveFrame(ProtocolUnit pu, int port)
            {
                RoutingEntry source = new RoutingEntry(pu.Stream,port);
                if (sources.ContainsKey(source))
                {
                    Buffer += String.Format("[{0}]> {1}", sources[source], pu.Message) + Environment.NewLine;
                    sink.log.LogMsg("Wiadomosc " + pu.Message + " z polaczenia " + sources[source]);
                    
                }
                else
                    sink.Log.LogMsg("Ramka: " + source.ToString());
            }
            public bool Add(RoutingEntry routingEntry, int connectionID)
            {

                if (connections.ContainsKey(connectionID) || sources.ContainsKey(routingEntry))
                    return false;
                else
                {
                    connections.Add(connectionID, routingEntry);
                    sources.Add(routingEntry, connectionID.ToString());
                    return true;
                }
            }

            //remove connection
            public bool Remove(int connectionID)
            {
                if (connections.ContainsKey(connectionID))
                {
                    sources.Remove(connections[connectionID]);
                    return connections.Remove(connectionID);
                }
                else
                    return false;
            }

        }

        private SinkReceiver receiver;
        public SinkReceiver Receiver { get { return receiver; } }

        public Sink(TransportLayer.Node node, int managerPort)
        {
            this.id = node.Id;
            this.name = (string)node.Name.Clone();
            this.log = new Log("Log urzadzenia " + Name);
            this.snp = new SinkSNP(this, managerPort);
            portIn = new PortIn(0);
            receiver = new SinkReceiver(this);
            portIn.SetReceiver(receiver);
        }

        public void Clean()
        {
            portIn.Clean();
            snp.Clean();
        }
    }
}